import axios from "axios"

axios.defaults.withCredentials = true

const route = {
    rootURL: "/gateway/api/jsonrpc.jsp"
}

var directJsonrpc = function (method, parameters, callback) {
    if (method && typeof method === "string" && parameters) {
        if (typeof parameters === "function") {
            callback = parameters
            parameters = []
        } else {
            if (!Array.isArray(parameters)) {
                parameters = [parameters]
            }
        }

        var query = {
            jsonrpc: "2.0",
            id: Date.now(),
            method: method,
            params: parameters
        }

        axios.post(route.rootURL, JSON.stringify(query)).then(function (response) {
            if (callback && typeof callback === "function") {
                if (response.data.error) {
                    callback(response.data.error, undefined)
                } else {
                    callback(undefined, response.data.result)
                }
            }
        }).catch(function (ex) {
            if (callback && typeof callback === "function") {
                let error = {
                    "code": 490,
                    "msg": ex.toString()
                }
                callback(error)
            }
        })
    } else {
        throw new Error("parameter format error")
    }
}

var saveCredential = function (id, key) {
    if (id && key) {
        window.localStorage.setItem("backend.paticipant.id", id)
        window.localStorage.setItem("backend.paticipant.key", key)
    } else if (!(id && window.localStorage.getItem("backend.paticipant.id") === id)) {
        window.localStorage.setItem("backend.paticipant.id", "")
        window.localStorage.setItem("backend.paticipant.key", "")
    }
}

var status = 0
var queue = []

var doParticipant = function (callback) {
    status = 1

    directJsonrpc("backend@user.participant", [{
        id: window.localStorage.getItem("backend.paticipant.id"),
        key: window.localStorage.getItem("backend.paticipant.key")
    }], function (error, result) {
        status = 0
        if (error) {
            callback(error)
        } else if (result) {
            saveCredential(result.id, result.key)

            queue.forEach(function (context) {
                directJsonrpc(context.path, context.parameters, context.callback)
            })
            callback(null, result)
        }

    })
}

var buildProxy = function (name, context) {
    return new Proxy(function () {
        var args = Array.prototype.slice.call(arguments, 0);
        return new Promise(function (resolve, reject) {
            jsonrpc(context.join("@") + "." + name, args, function (error, result) {
                if (error) {
                    reject(error);
                } else {
                    resolve(result);
                }
            });
        })
    }, {
        get: function (target, method) {
            if (!target[method]) {
                target[method] = buildProxy(method, context.concat([name]));
            }
            return target[method];
        }
    })
}

var jsonrpc = function (path, parameters, callback) {
    if (status === 0) {
        directJsonrpc(path, parameters, function (error, result) {
            if (error) {
                if (error.code === 592) {
                    doParticipant(function (error) {
                        if (error) {
                            callback(error)
                        } else {
                            directJsonrpc(path, parameters, callback)
                        }
                    })
                } else {
                    callback && callback(error)
                }
            } else {
                callback && callback(null, result)
            }
        })
    } else {
        queue.push({
            path: path,
            parameters: parameters,
            callback: callback
        })
    }
}

jsonrpc.direct = directJsonrpc
jsonrpc.saveCredential = saveCredential
jsonrpc.doParticipant = doParticipant

export default new Proxy(function () {
    return jsonrpc.apply(jsonrpc, arguments);
}, {
    "get": function (target, domain) {
        switch (domain) {
        case "direct":
            return directJsonrpc;
        case "saveCredential":
            return saveCredential;
        case "doParticipant":
            return doParticipant;
        default:
            if (["name", "length", "bind"].indexOf(name) < 0) {
                if (!target[domain]) {
                    target[domain] = new Proxy({}, {
                        get: function (subTarget, method) {
                            console.log(method)
                            if (["bind", "length", "name"].indexOf(method) < 0) {
                                if (!subTarget[method]) {
                                    subTarget[method] = buildProxy(method, [domain]);
                                }
                                return subTarget[method];
                            } else {
                                return subTarget[method];
                            }
                        }
                    })
                }
                return target[domain];
            } else {
                return target[domain];
            }
        }
    }
})